package com.zsr.common.utils;

import lombok.Data;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 增强版地址分割工具类（包含省市区街道，优化对县级市、直辖市、港澳台地区的处理）
 * 用于将完整地址分割为省、市、区县、街道和详细地址部分
 * 特别处理：
 * 1. 直辖市/特别行政区的市字段也设置为其全称。
 * 2. 正确识别地级市下辖的县级市。
 * 3. 支持香港特别行政区、澳门特别行政区、台湾省的地址解析。
 */
public class AddressSplitterUtil {

    // 省级/特别行政区划关键词
    // "省" 也用于处理台湾省
    private static final String[] PROVINCE_KEYWORDS = {
            "省", "自治区", "特别行政区"
    };

    // 明确的地级市替代关键词 (如自治州、地区、盟)
    private static final String[] PREFECTURE_LEVEL_KEYWORDS = {
            "自治州", "地区", "盟"
    };

    // 市级行政区划关键词 (用于初步识别地级市)
    private static final String[] CITY_KEYWORDS = {
            "市"
    };

    // 区县级行政区划关键词 (用于识别普通区县和县级市)
    // 添加 "市" 用于识别县级市
    private static final String[] DISTRICT_KEYWORDS = {
            "区", "县", "自治县", "旗", "自治旗", "市辖区", "市"
    };

    // 特殊的区县级标识 (县级市)
    private static final String[] COUNTY_LEVEL_CITY_KEYWORDS = {
            "县级市"
    };

    // 街道级行政区划关键词
    private static final String[] STREET_KEYWORDS = {
            "街道办事处", "街道办", "街道", "镇", "乡", "社区", "村委会", "居委会"
    };

    // 直辖市/特别行政区列表 (视为与直辖市具有相同地址结构)
    private static final Set<String> MUNICIPALITIES_OR_SPECIAL_REGIONS = new HashSet<>(Arrays.asList(
            "北京市", "上海市", "天津市", "重庆市",
            "香港特别行政区", "澳门特别行政区"
            // 台湾省按普通省份处理，因其结构类似 (省 -> 市 -> 区/县)
    ));

    /**
     * 地址分割结果类
     */
    @Data
    public static class AddressInfo {
        // Getter和Setter方法
        private String province;     // 省/特别行政区/台湾省
        private String city;         // 市 (地级市 或 直辖市/特别行政区 名称)
        private String district;     // 区/县 (包括县级市)
        private String street;       // 街道/镇/乡
        private String detail;       // 详细地址

        // 构造函数
        public AddressInfo() {}


        @Override
        public String toString() {
            return "AddressInfo{" +
                    "province='" + province + '\'' +
                    ", city='" + city + '\'' +
                    ", district='" + district + '\'' +
                    ", street='" + street + '\'' +
                    ", detail='" + detail + '\'' +
                    '}';
        }
    }

    /**
     * 封装提取结果
     */
    private static class ExtractResult {
        boolean found;
        String value;
        String remainingAddress;

        ExtractResult(boolean found, String value, String remainingAddress) {
            this.found = found;
            this.value = value;
            this.remainingAddress = remainingAddress;
        }
    }

    /**
     * 分割地址（包含省市区街道，优化对县级市、直辖市、港澳台的处理）
     * @param fullAddress 完整地址字符串
     * @return AddressInfo对象
     */
    public static AddressInfo splitAddress(String fullAddress) {
        AddressInfo addressInfo = new AddressInfo();

        if (fullAddress == null || fullAddress.trim().isEmpty()) {
            return addressInfo;
        }

        String address = fullAddress.trim();
        boolean isMunicipalityOrSpecialRegionProcessed = false;

        // 1. 检查并处理直辖市/特别行政区开头的情况
        for (String municipalityOrRegion : MUNICIPALITIES_OR_SPECIAL_REGIONS) {
            if (address.startsWith(municipalityOrRegion)) {
                addressInfo.setProvince(municipalityOrRegion);
                // *** 关键修改：直辖市/特别行政区的市字段也设置为其全称 ***
                addressInfo.setCity(municipalityOrRegion);
                address = address.substring(municipalityOrRegion.length()).trim();
                isMunicipalityOrSpecialRegionProcessed = true;
                break; // 找到就跳出循环
            }
        }

        // 2. 如果不是直辖市/特别行政区开头，则按常规流程提取省
        if (!isMunicipalityOrSpecialRegionProcessed) {
            ExtractResult provinceResult = extractProvince(address);
            if (provinceResult.found) {
                addressInfo.setProvince(provinceResult.value);
                address = provinceResult.remainingAddress;
            }
        }

        // 3. 提取地级市 (自治州、地区、盟 或 第一个 '市')
        if (!isMunicipalityOrSpecialRegionProcessed) {
            ExtractResult prefectureResult = extractPrefectureLevelCity(address);
            if (prefectureResult.found) {
                addressInfo.setCity(prefectureResult.value);
                address = prefectureResult.remainingAddress;
            } else {
                // 如果没有明确的地级市标识，查找第一个以 '市' 结尾的作为地级市
                ExtractResult cityResult = extractFirstGenericCity(address);
                if (cityResult.found) {
                    addressInfo.setCity(cityResult.value);
                    address = cityResult.remainingAddress;
                }
            }
        }

        // 4. 提取区/县 (包括县级市)
        // 优先查找 "xxx县级市" 格式
        ExtractResult countyLevelCityResult = extractCountyLevelCity(address);
        if (countyLevelCityResult.found) {
            addressInfo.setDistrict(countyLevelCityResult.value);
            address = countyLevelCityResult.remainingAddress;
        } else {
            // 查找区/县 (包括普通区县和县级市 '市')
            ExtractResult districtResult = extractDistrictOrCountyLevelCity(address);
            if (districtResult.found) {
                addressInfo.setDistrict(districtResult.value);
                address = districtResult.remainingAddress;
            }
        }

        // 5. 提取街道/镇/乡
        ExtractResult streetResult = extractStreet(address);
        if (streetResult.found) {
            addressInfo.setStreet(streetResult.value);
            address = streetResult.remainingAddress;
        }

        // 6. 剩余部分作为详细地址
        addressInfo.setDetail(address);

        return addressInfo;
    }


    // --- 内部辅助方法 ---

    /**
     * 提取省/特别行政区信息 (不包括直辖市/特别行政区)
     * 也用于提取台湾省信息
     */
    private static ExtractResult extractProvince(String address) {
        for (String keyword : PROVINCE_KEYWORDS) {
            int index = address.indexOf(keyword);
            if (index > 0) {
                int start = findStartIndex(address, index);
                String province = address.substring(start, index + keyword.length()).trim();
                String remaining = address.substring(index + keyword.length()).trim();
                return new ExtractResult(true, province, remaining);
            }
        }
        return new ExtractResult(false, null, address);
    }

    /**
     * 提取地级市 (自治州、地区、盟)
     */
    private static ExtractResult extractPrefectureLevelCity(String address) {
        for (String keyword : PREFECTURE_LEVEL_KEYWORDS) {
            int index = address.indexOf(keyword);
            if (index > 0) {
                int start = findStartIndex(address, index);
                String city = address.substring(start, index + keyword.length()).trim();
                String remaining = address.substring(index + keyword.length()).trim();
                return new ExtractResult(true, city, remaining);
            }
        }
        return new ExtractResult(false, null, address);
    }

    /**
     * 提取第一个普通的'市' (用于地级市)
     * 这个方法只查找第一个匹配的 '市'，不管后面是否还有 '市'
     */
    private static ExtractResult extractFirstGenericCity(String address) {
        for (String keyword : CITY_KEYWORDS) { // 主要是 "市"
            int index = address.indexOf(keyword);
            if (index > 0) {
                int start = findStartIndex(address, index);
                String city = address.substring(start, index + keyword.length()).trim();
                String remaining = address.substring(index + keyword.length()).trim();
                return new ExtractResult(true, city, remaining);
            }
        }
        return new ExtractResult(false, null, address);
    }


    /**
     * 提取区/县信息 (包括普通区县和县级市 '市')
     * 此方法会查找 DISTRICT_KEYWORDS 中的任意一个关键词
     */
    private static ExtractResult extractDistrictOrCountyLevelCity(String address) {
        // 为了优先匹配长的区县名，我们按关键词长度降序排序查找
        // 这里简化处理，按常见顺序查找
        // 实际应用中可能需要更复杂的排序或正则匹配

        // 1. 先查找 "县级市"
        ExtractResult countyLevelCityResult = extractCountyLevelCity(address);
        if (countyLevelCityResult.found) {
            return countyLevelCityResult;
        }

        // 2. 再查找其他区县关键词 (区, 县, 市等)
        for (String keyword : DISTRICT_KEYWORDS) {
            int index = address.indexOf(keyword);
            if (index > 0) {
                int start = findStartIndex(address, index);
                String district = address.substring(start, index + keyword.length()).trim();
                String remaining = address.substring(index + keyword.length()).trim();
                return new ExtractResult(true, district, remaining);
            }
        }
        return new ExtractResult(false, null, address);
    }

    /**
     * 提取"xxx县级市"格式的信息 (从 extractDistrictOrCountyLevelCity 中分离出来以便复用)
     */
    private static ExtractResult extractCountyLevelCity(String address) {
        for (String keyword : COUNTY_LEVEL_CITY_KEYWORDS) {
            int index = address.indexOf(keyword);
            if (index >= 0) { // "县级市" 可能在开头
                int start = findStartIndex(address, index);
                // 需要获取 "xxx县级市" 中的 "xxx"
                String namePart = address.substring(start, index).trim();
                if (!namePart.isEmpty()) {
                    String countyLevelCity = namePart + keyword;
                    String remaining = address.substring(index + keyword.length()).trim();
                    return new ExtractResult(true, countyLevelCity, remaining);
                }
            }
        }
        return new ExtractResult(false, null, address);
    }


    /**
     * 提取街道信息
     */
    private static ExtractResult extractStreet(String address) {
        // 按照长度从长到短排序关键词，优先匹配长的 (这里简化处理，按数组顺序)
        for (String keyword : STREET_KEYWORDS) {
            int index = address.indexOf(keyword);
            if (index >= 0) {
                int start = findStartIndex(address, index);
                String street = address.substring(start, index + keyword.length()).trim();
                String remaining = address.substring(index + keyword.length()).trim();
                return new ExtractResult(true, street, remaining);
            }
        }
        return new ExtractResult(false, null, address);
    }

    /**
     * 找到地址片段的开始索引
     */
    private static int findStartIndex(String address, int endIndex) {
        int start = 0;
        for (int i = endIndex; i >= 0; i--) {
            char c = address.charAt(i);
            if (i == 0 || c == ',' || c == '，' || c == ' ') {
                start = i + (i == 0 ? 0 : 1);
                break;
            }
        }
        return start;
    }

    // 测试方法
    public static void main(String[] args) {
        // 测试用例 - 包含街道的地址 (大陆)
        String[] testAddressesMainlandWithStreet = {
                "湖南省荆州市石首市晴川学院菜鸟驿站",
                "广东省深圳市南山区粤海街道科技园南区深南大道10000号",
                "江苏省南京市鼓楼区中央门街道中央路200号",
                "湖北省荆州市石首市晴川学院菜鸟驿站",
                "湖南省湘西土家族苗族自治州吉首市乾州街道",
                "河北省石家庄市藁城区廉州镇",
                "山东省菏泽市曹县磐石街道",
                "新疆维吾尔自治区巴音郭楞蒙古自治州库尔勒市朝阳街道",
                "新疆维吾尔自治区乌鲁木齐市沙依巴克区西北路",
                "浙江省杭州市桐庐县分水镇",
                "浙江省杭州市建德市新安江街道",
        };

        System.out.println("=== 大陆地址测试 (包含街道，重点测试县级市) ===");
        for (String address : testAddressesMainlandWithStreet) {
            AddressInfo info = splitAddress(address);
            System.out.println("原始地址: " + address);
            System.out.println("分割结果: " + info);
            if (address.contains("荆州市石首市")) {
                System.out.println("  -> 关键检查 (荆州市石首市): City=" + info.getCity() + ", District=" + info.getDistrict());
            }
            System.out.println("------------------------");
        }

        // 测试用例 - 不包含街道的地址 (大陆)
        String[] testAddressesMainlandWithoutStreet = {
                "北京市朝阳区建国路88号万达广场",
                "广东省深圳市南山区科技园南区深南大道10000号",
                "江苏省南京市鼓楼区中央路200号",
                "湖北省荆州市石首市",
                "新疆维吾尔自治区巴音郭楞蒙古自治州库尔勒市",
                "浙江省杭州市建德市",
                "湖南省荆州市石首市",
        };

        System.out.println("=== 大陆地址测试 (不包含街道) ===");
        for (String address : testAddressesMainlandWithoutStreet) {
            AddressInfo info = splitAddress(address);
            System.out.println("原始地址: " + address);
            System.out.println("分割结果: " + info);
            if (address.contains("荆州市石首市")) {
                System.out.println("  -> 关键检查 (荆州市石首市): City=" + info.getCity() + ", District=" + info.getDistrict());
            }
            System.out.println("------------------------");
        }

        // 测试直辖市/特别行政区
        String[] testSpecialRegions = {
                "上海市浦东新区张江高科技园区",
                "重庆市渝北区人和街道",
                "北京市海淀区中关村大街",
                "天津市滨海新区塘沽街道",
                "香港特别行政区中西区皇后大道中15号",
                "澳门特别行政区大堂区葡京路",
        };
        System.out.println("=== 直辖市/特别行政区测试 (验证市字段) ===");
        for (String address : testSpecialRegions) {
            AddressInfo info = splitAddress(address);
            System.out.println("原始地址: " + address);
            System.out.println("分割结果: " + info);
            System.out.println("  -> 验证: Province=" + info.getProvince() + ", City=" + info.getCity() + ", District=" + info.getDistrict());
            System.out.println("------------------------");
        }

        // 测试台湾省 (结构类似大陆省份)
        String[] testTaiwan = {
                "台湾省台北市中正区忠孝东路一段1号",
                "台湾省高雄市苓雅区三多一路186号",
                "台湾省台中市西屯区台湾大道三段999号",
        };
        System.out.println("=== 台湾省地址测试 ===");
        for (String address : testTaiwan) {
            AddressInfo info = splitAddress(address);
            System.out.println("原始地址: " + address);
            System.out.println("分割结果: " + info);
            System.out.println("  -> 验证: Province=" + info.getProvince() + ", City=" + info.getCity() + ", District=" + info.getDistrict());
            System.out.println("------------------------");
        }
    }
}



